package com.binance.binancedemo.recycler;

import android.graphics.Canvas;
import android.graphics.Rect;
import android.support.v7.widget.RecyclerView;
import android.view.View;

/**
 */
public class LinearItemDecoration extends RecyclerView.ItemDecoration {

    private int mDividerHeight;

    @Override
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
        if (parent.getAdapter() == null || !(parent.getAdapter() instanceof BaseRecyclerAdapter)) {
            return;
        }
        final int childCount = parent.getChildCount();
        Rect tempOutRect = new Rect();
        Rect tempDefaultRect = new Rect();
        BaseRecyclerAdapter adapter = (BaseRecyclerAdapter) parent.getAdapter();
        for (int i = 0; i < childCount; i++) {
            View child = parent.getChildAt(i);
            boolean isFirst = isFirst(child, parent);
            boolean isLast = isLast(child, parent);
            getDefaultRect(tempDefaultRect, isFirst, isLast);
            int position = parent.getChildViewHolder(child).getAdapterPosition();
            BaseRecyclerCell cell = adapter.getItem(position);

            boolean drawDefault = true;
            boolean setRect = false;
            Rect curRect, beforeRect = cell == null ? null : cell.getDecorationRect();
            if (cell instanceof ILinearDecoration) {
                BaseRecyclerCell preCell = ((BaseRecyclerAdapter) parent.getAdapter()).getItem(position - 1);
                BaseRecyclerCell nextCell = ((BaseRecyclerAdapter) parent.getAdapter()).getItem(position + 1);
                tempOutRect.set(0, 0, 0, 0);
                setRect = ((ILinearDecoration) cell).setDecorationRect(preCell, nextCell, tempOutRect, tempDefaultRect);
                curRect = setRect ? tempOutRect : tempDefaultRect;
                Rect correctRect = getCorrectRect(curRect, beforeRect);
                drawDefault = !((ILinearDecoration) cell).drawDecoration(
                        correctRect,
                        c,
                        child,
                        parent,
                        state);
            }
            if (drawDefault) {
                curRect = setRect ? tempOutRect : tempDefaultRect;
                Rect correctRect = getCorrectRect(curRect, beforeRect);
                if (isLast && isFirst) {
                    drawDefaultDecorationSingle(correctRect, c, child, parent, state);
                } else if (isFirst) {
                    drawDefaultDecorationFirst(correctRect, c, child, parent, state);
                } else if (isLast) {
                    drawDefaultDecorationLast(correctRect, c, child, parent, state);
                } else {
                    drawDefaultDecorationMid(correctRect, c, child, parent, state);
                }
            }
        }
    }

    /**
     * 在notify局部item的时候，可能会导致原来最后一个cell变成不是最后一个或者相反，导致计算出来的Decoration区域变化，
     * 但是这时候又不回去调用getItemOffsets，使得我计算出来的与RecyclerView存储的不一致，就会有部分区域没有画上
     * 分割线。因此按老的区域进行绘制
     * ps：如果想更新RecyclerView内部的区域必须调用notifyItemChange，然而此时Feed页正在移除和添加footer，
     * 两边notify冲突会导致错误调用某些cell的onViewRecycled
     *
     * @param curRect
     * @param beforeRect
     * @return
     */
    private Rect getCorrectRect(Rect curRect, Rect beforeRect) {
        if (beforeRect != null && !beforeRect.equals(curRect)) {
//            L.e("Cell Decoration区域异常：" + beforeRect.toShortString() + " to " + curRect.toShortString());
            return beforeRect;
        }
        return curRect;
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        if (parent.getAdapter() == null || !(parent.getAdapter() instanceof BaseRecyclerAdapter)) {
            super.getItemOffsets(outRect, view, parent, state);
            return;
        }
        int itemPosition = parent.getChildAdapterPosition(view);
        if (itemPosition < 0) {
            return;
        }
        int position = parent.getChildViewHolder(view).getAdapterPosition();
        BaseRecyclerCell cell = ((BaseRecyclerAdapter) parent.getAdapter()).getItem(position);
        boolean isFirst = position == 0;
        boolean isLast = position == parent.getAdapter().getItemCount() - 1;
        Rect defaultRect = getDefaultRect(null, isFirst, isLast);
        if (cell instanceof ILinearDecoration) {
            BaseRecyclerCell preCell = ((BaseRecyclerAdapter) parent.getAdapter()).getItem(position - 1);
            BaseRecyclerCell nextCell = ((BaseRecyclerAdapter) parent.getAdapter()).getItem(position + 1);
            boolean set = ((ILinearDecoration) cell).setDecorationRect(preCell, nextCell, outRect, defaultRect);
            if (!set) {
                outRect.set(defaultRect);
            }
        } else {
            outRect.set(defaultRect);
        }
        if (cell != null) {
            cell.setDecorationRect(new Rect(outRect));
        }
    }

    protected void drawDefaultDecorationMid(Rect outRect, Canvas c, View child, RecyclerView parent, RecyclerView.State state) {

    }

    protected void drawDefaultDecorationFirst(Rect outRect, Canvas c, View child, RecyclerView parent, RecyclerView.State state) {

    }

    protected void drawDefaultDecorationLast(Rect outRect, Canvas c, View child, RecyclerView parent, RecyclerView.State state) {

    }

    protected void drawDefaultDecorationSingle(Rect outRect, Canvas c, View child, RecyclerView parent, RecyclerView.State state) {

    }

    protected final boolean isFirst(View child, RecyclerView parent) {
        int position = parent.getChildViewHolder(child).getAdapterPosition();
        return position == 0;
    }

    protected final boolean isLast(View child, RecyclerView parent) {
        int position = parent.getChildViewHolder(child).getAdapterPosition();
        return position == parent.getAdapter().getItemCount() - 1;
    }

    protected Rect getDefaultRect(Rect rect, boolean isFirst, boolean isLast) {
        if (rect == null) {
            rect = new Rect();
        }
        if (isLast && isFirst) {
            rect.set(0, mDividerHeight, 0, mDividerHeight);
        } else if (isFirst) {
            rect.set(0, mDividerHeight, 0, mDividerHeight / 2);
        } else if (isLast) {
            rect.set(0, mDividerHeight / 2, 0, mDividerHeight);
        } else {
            rect.set(0, mDividerHeight / 2, 0, mDividerHeight / 2);
        }
        return rect;
    }

    public void setDividerHeight(int height) {
        mDividerHeight = height;
    }
}
